<template>
    <div class="form">
        <el-form ref="form" :model="obj.data" label-width="80px">
            <el-form-item label="角色名称" prop="name" :rules="[formRulesMixin.notNull]">
                <el-input v-model="obj.data.name" clearable autocomplete="off"></el-input>
            </el-form-item>
            <el-form-item label="权限">
                <div class="checkboxgroup">
                    <div v-for="(a,a_index) in obj.menu" :key="a_index" class="item">
                        <el-checkbox v-model="a.checked" :disabled="a.disabled" :indeterminate="a.indeterminate" class="checkbox1" @change="subChange($event, a, obj.menu)">{{a.label}}{{ `${a.disabled?'(默认配置)':''}` }}</el-checkbox>
                        <div class="subdiv">
                            <div class="subitem" v-for="(b,b_index) in a.sub" :key="b_index">
                                <el-checkbox v-model="b.checked" :disabled="b.disabled" :indeterminate="b.indeterminate" @change="subChange($event, b, a)" class="checkbox1">{{b.label}}{{ `${b.disabled?'(默认配置)':''}` }}</el-checkbox>
                                <div class="subsubitem" v-for="(c,c_index) in b.powers" :key="c_index">
                                    <el-checkbox v-model="c.checked" :disabled="c.disabled" @change="powerChange($event, c, b)" class="checkbox1">{{c.name}}{{ `${c.disabled?'(默认配置)':''}` }}</el-checkbox>
                                </div>
                                <div class="subsubitem" v-for="(c,c_index) in b.sub" :key="c_index">
                                    <el-checkbox v-model="c.checked" :disabled="c.disabled"  :indeterminate="c.indeterminate" @change="subChange($event, c, a)" class="checkbox1">{{c.label}}{{ `${c.disabled?'(默认配置)':''}` }}</el-checkbox>
                                    <div class="subsubitem" v-for="(d,d_index) in c.powers" :key="d_index">
                                        <el-checkbox v-if="d.name" v-model="d.checked" :disabled="d.disabled" @change="powerChange($event, d, c)" class="checkbox1">{{d.name}}{{ `${d.disabled?'(默认配置)':''}` }}</el-checkbox>
                                    </div>
                                    <div class="subsubitem" v-for="(d,d_index) in c.sub" :key="d_index">
                                        <el-checkbox v-model="d.checked" :disabled="d.disabled" :indeterminate="d.indeterminate" @change="subChange($event, d, a)" class="checkbox1">{{d.label}}{{ `${d.disabled?'(默认配置)':''}` }}</el-checkbox>
                                        <div class="subsubitem" v-for="(e,e_index) in d.powers" :key="e_index">
                                            <el-checkbox v-model="e.checked" :disabled="e.disabled" @change="powerChange($event, e, d)" class="checkbox1">{{e.name}}{{ `${e.disabled?'(默认配置)':''}` }}</el-checkbox>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </el-form-item>
        </el-form>
        <div class="btns">
            <el-button @click="$emit('close')">取消</el-button>
            <el-button type="primary" @click="upData">提交</el-button>
        </div>
    </div>
</template>

<script setup>
    import { reactive, getCurrentInstance } from 'vue'
    let { proxy } = getCurrentInstance()
    const emit = defineEmits(['init', 'close']) //此处要完全对应，采用固定的update:prop属性
    const props = defineProps({
        id: { type: Number, require: true },
    })

    let obj = reactive({
        data:{
            role_id: props.id,
            name: "",
            authority: "",
        },
        menu:[]
    })

    let allMenu = () => {
        return new Promise((resolve, reject) => {
            proxy.$ajax({
                url: '/manager/menu',
                data: {},
                bfLoading: true
            }).then(d => {
                resolve(d.msg)
            }).catch(e => {
                reject(e)
            })
        })
    }
    let getpowers = () => {
        return new Promise((resolve, reject) => {
            if(props.id){
                proxy.$ajax({
                    url: '/manager/role/get',
                    data: {role_id: props.id},
                    bfLoading: true
                }).then(d => {
                    if(d.success&&d.msg){
                        obj.data.name = d.msg.name
                        const getPermissions=(tree)=>{
                            const permissions = {};
                            
                            const traverse=(node)=>{
                                const label_id = `${node.label}_${node.component}`
                                if(node.powers.length){
                                    permissions[label_id] = node.powers;
                                }
                                if(node.sub&&node.sub.length){
                                    for (const child of node.sub) {
                                        traverse(child);  
                                    }
                                }
                            }
                            for (const node of tree) {
                                traverse(node);
                            }
                            return permissions;
                        }
                        let powers = getPermissions(d.msg.authority)
                        resolve(powers||{})
                    }else{
                        resolve({})
                    }
                }).catch(e => {
                    resolve({})
                })
            }else{
                resolve({})
            }
        })
    }
    let setmenu = async ()=>{
        let menu = await allMenu()
        // console.log(menu)
        // 拿角色权限
        let nowPowers = await getpowers()
        // console.log(nowPowers);
        const setmenu=(menus,parents)=>{
            menus.map(node=>{
                //处理
                let key = `${node.label}_${node.component}`
                let mypowers = nowPowers[key]||[]
                let mypowers_strs = (mypowers.map(e=>e.name))||[]
                let ischeck_num = 0
                // const powers = node.powers.filter(e=>e.name)
                // node.powers = powers||[]
                node.powers.map(e=>{
                    e.parent_strs = parents.concat([key])||[]
                    if(mypowers_strs.includes(e.name)){
                        ischeck_num++
                        e.checked = true
                    }
                })
                
                node.parent_strs = parents
                if(node.sub&&node.sub.length){
                    setmenu(node.sub,parents.concat([key]))
                }
            })
        }
        setmenu(menu,[])
        //全部检查
        obj.menu = menu
        // console.log(obj.menu); //此时还是对的
        await setMenustatus()
        obj.menu = menu
        // console.log(obj.menu); //此时还是对的
    }

    setmenu()

    const subChange=(e,item)=>{
        item.checked = e
        item.indeterminate = false
        const setChild=(obj)=>{
            obj.sub.map(ev=>{
                ev.checked = e
                ev.indeterminate = false
                setChild(ev)
            })
            obj.powers.map(ev=>{
                ev.checked = e
            })
        }
        setChild(item)
        setTimeout(() => {
            setMenustatus(item.parent_strs)
        }, 10);
    }
    const powerChange=(e, item)=>{
        item.checked = e
        setMenustatus(item.parent_strs)
    }
    const setMenustatus = (parent_strs) => {
        return new Promise(async (res,rejj)=>{
            const set=(menus)=>{
                return new Promise(async(resovle,rej)=>{
                    let menus_ =[]   
                    for (let idx = 0; idx < menus.length; idx++) {
                        let node = menus[idx];
                        let key = `${node.label}_${node.component}`
                        if(!parent_strs||(parent_strs&&parent_strs.includes(key))){//只处理所有父级别
                            if(node.sub&&node.sub.length){
                                let sub_ = await set(node.sub)
                                node.sub = sub_
                                let checks = node.powers.filter(e=>e.checked)
                                let subchecks = node.sub.filter(e=>e.checked)
                                let indeterminates = node.sub.filter(e=>e.indeterminate)
                                let checked_num = checks.length+subchecks.length
                                node.checked = checked_num==node.powers.length+node.sub.length
                                node.indeterminate = (checked_num>0&&checked_num<node.powers.length+node.sub.length)||(checked_num==0&&indeterminates.length>0)
                                menus_.push(node)
                            }else{
                                let checks =  node.powers.filter(e=>e.checked)
                                node.checked = checks.length==node.powers.length&&node.powers.length!=0
                                node.indeterminate = checks.length>0&&checks.length<node.powers.length
                                menus_.push(node)
                            }
                        }else{
                            menus_.push(node)
                        }
                        resovle(menus_)
                    }
                })
            }
            let menu_ = await set(obj.menu)
            setTimeout(() => {
                obj.menu = menu_
            }, 100);
            res(true)
        })
    }

    let upData = () => {
        proxy.$refs['form'].validate(async valid => {
            if (valid) {
                let menu = JSON.parse(JSON.stringify(obj.menu))
                // console.log(menu);
                // return
                const get=()=>{
                    new Promise((res,rej)=>{
                        let set=(menus)=>{
                            menus.map(e=>{
                                // e.show = e.checked||e.indeterminate
                                delete e.checked
                                delete e.disabled
                                delete e.indeterminate
                                delete e.parent_strs
                                let powers = e.powers.filter(ev=>ev.checked)
                                powers.map(ev=>{
                                    ev.disabled = ev.disabled?true:false
                                    delete ev.checked
                                    delete ev.parent_strs
                                })
                                e.powers = powers
                                set(e.sub||[])
                            })
                        }
                        set(menu)
                    })
                }
                await get()
                obj.data.authority = JSON.stringify(menu)
                // console.log(menu)
                proxy.$ajax({
                    url: '/manager/role/design',
                    data: obj.data,
                    bfLoading: true
                }).then(data => {
                    // console.log(date)
                    if(data.success){
                        proxy.elMessageMixin(`角色${obj.data.role_id > 0 ? '修改' : '添加'}成功`, 'success')
                        proxy.$emit('close')
                        proxy.$emit('init')
                    }else{
                        ElMessage({ message: data.err, type: 'error', duration: 2 * 1000 })
                    }
                }).catch(() => {})
            } else {
                return false
            }
        })
    }
</script>

<style scoped>
    .checkboxgroup { padding-top: 5px; }
    .checkbox1 { height:22px; font-weight: normal; }
    .item { padding-bottom: 10px; line-height: 0; }
    .subdiv { display: flex; flex-wrap: wrap; padding-left: 20px; }
    .subitem { padding-left:10px; }
    .subsubitem { padding-left: 30px; }
</style>

